home *** CD-ROM | disk | FTP | other *** search
/ Aminet 51 / Aminet 51 (2002)(GTI - Schatztruhe)[!][Oct 2002].iso / Aminet / dev / src / xad_DImp.lha / DImp.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-08-21  |  10.9 KB  |  396 lines

  1. /* Disk Imploder (DImp) disk archiver client for XAD.
  2.  * Copyright (C) 2000-2001 Stuart Caie <kyzer@4u.net>
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  * 
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  * 
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */
  18.  
  19. /* This XAD client reads DImp disk files, either normal data files
  20.  * or ones with executable headers (1.00 and 2.27 headers known),
  21.  * and writes them out as ADF files, or  allows them to be written
  22.  * to standard Amiga formatted disks.
  23.  * The DImp format is (C) 1988-1991 Albert-Jan Brouwer
  24.  *
  25.  * $VER: DImp.c 1.3 (20.08.2001)
  26.  */
  27.  
  28. #include <libraries/xadmaster.h>
  29. #include <proto/xadmaster.h>
  30.  
  31. #include "SDI_compiler.h"
  32. #include "ConvertE.c"
  33.  
  34. #ifndef XADMASTERFILE
  35. #define DImp_Client      FirstClient
  36. #define NEXTCLIENT      NULL
  37. const UBYTE version[] = "$VER: DImp 1.3 (20.08.2001)";
  38. #endif
  39. #define DIMP_VERSION     1
  40. #define DIMP_REVISION    3
  41.  
  42. #define XADBASE REG(a6, struct xadMasterBase *xadMasterBase)
  43.  
  44. /* work-doing macros */
  45. #define SKIP(offset) if ((err = xadHookAccess(XADAC_INPUTSEEK, \
  46.   (ULONG)(offset), NULL, ai))) goto exit_handler
  47. #define READ(buffer,length) if ((err = xadHookAccess(XADAC_READ, \
  48.   (ULONG)(length), (APTR)(buffer), ai))) goto exit_handler
  49. #define WRITE(buffer,length) if ((err = xadHookAccess(XADAC_WRITE, \
  50.   (ULONG)(length), (APTR)(buffer), ai))) goto exit_handler
  51. #define COPY(length) if ((err = xadHookAccess(XADAC_COPY, \
  52.   (ULONG)(length), NULL, ai))) goto exit_handler
  53. #define ALLOC(t,v,l) if (!((v) = (t) xadAllocVec((l),0x10000))) \
  54.   ERROR(NOMEMORY)
  55. #define ALLOCOBJ(t,v,kind,tags) \
  56.   if (!((v) = (t) xadAllocObjectA((kind),(tags)))) ERROR(NOMEMORY)
  57. #define FREE(obj) xadFreeObjectA((APTR)(obj),NULL)
  58. #define ERROR(error) do { err = XADERR_##error; goto exit_handler; } while(0)
  59.  
  60.  
  61.  
  62.  
  63. #define DIMP_CYLSIZE  (2*11*512)
  64.  
  65. /* DImp's info-table */
  66. #define dinf_cksum      (0)   /* ULONG checksum               */
  67. #define dinf_compmode   (4)   /* UWORD compression_mode       */
  68. #define dinf_bitmap     (6)   /* UBYTE disk_bitmap[10]        */
  69. #define dinf_ctable1    (16)  /* UBYTE compression_table1[28] */
  70. #define dinf_ctable2    (44)  /* UBYTE compression_table2[28] */
  71. #define dinf_textplen   (72)  /* ULONG textmsg_packed_len     */
  72. #define dinf_textulen   (76)  /* ULONG textmsg_unpacked_len   */
  73. #define dinf_textcksum  (80)  /* ULONG textmsg_checksum       */
  74. #define dinf_cylinfo    (84)  /* ULONG cylinder_info[80]      */
  75. #define dinf_SIZEOF     (404) /* ...maximum length            */
  76.  
  77. static INLINE int DImp_bitmap(UBYTE *info, int track) {
  78.   return info[dinf_bitmap + (track>>3)] & (1 << (7-(track&7)));
  79. }
  80.  
  81. static ULONG DImp_checksum(UBYTE *data, ULONG len) {
  82.   ULONG cksum = 0;
  83.   while (len > 1) {
  84.     cksum += EndGetM16(data);
  85.     data += 2; len -= 2;
  86.   }
  87.   if (len) cksum += (*data << 8);
  88.   return (cksum+7) & 0xFFFFFFFF;
  89. }
  90.  
  91.  
  92. /* de-implosion */
  93.  
  94. /* add.b d3,d3; bne gotbit; move.b -(a3),d3; addx.b d3,d3; gotbit: */
  95. #define GETBIT do { \
  96.  bit = bitbuf & 0x80; bitbuf <<= 1; \
  97.  if (!bitbuf) { bit2 = bit; bitbuf = *--inp; bit = bitbuf & 0x80; \
  98.    bitbuf <<= 1; if (bit2) bitbuf++; }; \
  99. } while (0)
  100.  
  101. static UBYTE explode_tab1[] = { 6, 10, 10, 18 };
  102. static UBYTE explode_tab2[] = { 1, 1, 1, 1, 2, 3, 3, 4, 4, 5, 7, 14 };
  103.  
  104. static int DImp_explode(UBYTE *buf, UBYTE *table, ULONG inlen, ULONG outlen) {
  105.   UBYTE *inp  = buf + inlen-5;
  106.   UBYTE *outp = buf + outlen;
  107.   UBYTE *rep, bitbuf, bit, bit2;
  108.   ULONG litlen, matchlen, x, y, z;
  109.  
  110.   if (inlen & 1) {
  111.     bitbuf = inp[4];
  112.     litlen = EndGetM32(inp);
  113.   }
  114.   else {
  115.     bitbuf = inp[0];
  116.     litlen = EndGetM32(inp+1);
  117.   }
  118.  
  119.   while (1) {
  120.     if (outp-litlen < buf) return 0;
  121.     while (litlen--) *--outp = *--inp;
  122.  
  123.     /* main exit point - after the literal copy */
  124.     if (outp <= buf) break;
  125.  
  126.     GETBIT; if (bit) {
  127.       GETBIT; if (bit) {
  128.         GETBIT; if (bit) {
  129.           GETBIT; if (bit) {
  130.             matchlen = 0;
  131.             GETBIT; if (bit) {
  132.               x = 3;
  133.               matchlen = *--inp - 1;
  134.             }
  135.             else {
  136.               x = 3;
  137.               matchlen <<= 1; GETBIT; if (bit) matchlen++;
  138.               matchlen <<= 1; GETBIT; if (bit) matchlen++;
  139.               matchlen <<= 1; GETBIT; if (bit) matchlen++;
  140.               matchlen += 5;
  141.             }
  142.           } else x=3, matchlen=4;
  143.         } else x=2, matchlen=3;
  144.       } else x=1, matchlen=2;
  145.     } else x=0, matchlen=1;
  146.  
  147.     y = 0;
  148.     z = x;
  149.     GETBIT; if (bit) {
  150.       GETBIT; if (bit) {
  151.         y = explode_tab1[x];
  152.         x += 8;
  153.       }
  154.       else {
  155.         y = 2;
  156.         x += 4;
  157.       }
  158.     }
  159.  
  160.     x = explode_tab2[x];
  161.     litlen = 0;
  162.     while (x--) { litlen<<=1; GETBIT; if (bit) litlen++; }
  163.     litlen += y;
  164.  
  165.     rep = outp + 1;
  166.     x = z;
  167.  
  168.     GETBIT; if (bit) {
  169.       z <<= 1; GETBIT;
  170.       if (bit) { rep += EndGetM16(table+z+8); x += 8; }
  171.       else     { rep += EndGetM16(table+z);   x += 4; }
  172.     }
  173.     x = table[x+16];
  174.  
  175.     y = 0;
  176.     while (x--) { y<<=1; GETBIT; if (bit) y++; }
  177.     rep += y;
  178.  
  179.     if (outp-matchlen < buf) return 0;
  180.     do { *--outp = *--rep; } while (matchlen--);
  181.   }
  182.  
  183.   /* return 1 if we used up all input bytes (as we should) */
  184.   return (inp == buf);
  185. }
  186.  
  187.  
  188.  
  189.  
  190. ASM(BOOL) DImp_RecogData(REG(d0, ULONG size), REG(a0, UBYTE *d), XADBASE) {
  191.   ULONG infolen;
  192.   if (d[0]!='D' || d[1]!='I' || d[2]!='M' || d[3]!='P') return 0;
  193.   infolen = EndGetM32(d+4);
  194.   return (BOOL) (infolen > 4 && infolen <= dinf_SIZEOF);
  195. }
  196.  
  197. ASM(LONG) SAVEDS DImp_GetInfo(REG(a0, struct xadArchiveInfo *ai), XADBASE) {
  198.   UBYTE buffer[8], *info, *text;
  199.   ULONG infolen, textplen, textulen;
  200.   struct xadDiskInfo *di = NULL;
  201.   struct xadTextInfo *ti;
  202.   LONG err = XADERR_OK;
  203.   int x;
  204.  
  205.   ALLOCOBJ(struct xadDiskInfo *, di, XADOBJ_DISKINFO, NULL);
  206.   ai->xai_DiskInfo     = di;
  207.   di->xdi_EntryNumber  = 1;
  208.   di->xdi_SectorSize   = 512;
  209.   di->xdi_TotalSectors = 80 * 22;
  210.   di->xdi_Cylinders    = 80;
  211.   di->xdi_CylSectors   = 22;
  212.   di->xdi_Heads        = 2;
  213.   di->xdi_TrackSectors = 11;
  214.  
  215.   /* read "DIMP" and info table length */
  216.   READ(buffer, 8);
  217.   infolen = EndGetM32(buffer+4);
  218.  
  219.   /* allocate and read info table */
  220.   ALLOC(UBYTE *, info, dinf_SIZEOF);
  221.   ai->xai_PrivateClient = (APTR) info;
  222.   READ(info, infolen);
  223.  
  224.   /* info table checksum */
  225.   if (EndGetM32(info+dinf_cksum) != DImp_checksum(info+4, infolen-4))
  226.     ERROR(CHECKSUM);
  227.  
  228.   /* look for start and end cylinders */
  229.   for (x=0; x<80; x++) if (DImp_bitmap(info, x)) break;
  230.   di->xdi_LowCyl = x;
  231.   if (x == 80) ERROR(EMPTY);
  232.  
  233.   for (x=79; x>=0; x--) if (DImp_bitmap(info, x)) break;
  234.   di->xdi_HighCyl = x;
  235.  
  236.  
  237.   textplen = EndGetM32(info+dinf_textplen);
  238.   textulen = EndGetM32(info+dinf_textulen);
  239.  
  240.   di->xdi_Flags   = XADDIF_SEEKDATAPOS;
  241.   di->xdi_DataPos = ai->xai_InPos + textplen;
  242.  
  243.   if (textulen) {
  244.     ALLOCOBJ(struct xadTextInfo *, ti, XADOBJ_TEXTINFO, NULL);
  245.     ALLOC(UBYTE *, text, (ti->xti_Size = textulen)+1);
  246.     di->xdi_TextInfo = ti;
  247.     ti->xti_Text     = text;
  248.  
  249.     READ(text, textplen);
  250.     text[textulen] = 0;
  251.  
  252.     if (textulen != textplen && !DImp_explode(text, info+dinf_ctable1,
  253.       textplen, textulen)) ERROR(DECRUNCH);
  254.   }
  255.   else {
  256.     di->xdi_TextInfo = NULL;
  257.   }
  258.  
  259. exit_handler:
  260.   if (err) {
  261.     if (!di) return err;
  262.     ai->xai_Flags |= XADAIF_FILECORRUPT;
  263.     ai->xai_LastError = err;
  264.   }
  265.   return XADERR_OK;
  266. }
  267.  
  268.  
  269. ASM(LONG) SAVEDS DImp_UnArchive(REG(a0, struct xadArchiveInfo *ai), XADBASE) {
  270.   UBYTE *buf = NULL, *info = (UBYTE *) ai->xai_PrivateClient, *p;
  271.   struct xadDiskInfo *di = ai->xai_CurDisk;
  272.   ULONG cyl, x;
  273.   LONG err;
  274.  
  275.   ALLOC(UBYTE *, buf, DIMP_CYLSIZE);
  276.   for (cyl = di->xdi_LowCyl; cyl <= ai->xai_HighCyl; cyl++) {
  277.     if (cyl >= ai->xai_LowCyl) {
  278.       /* extracting */
  279.  
  280.       /* clear the buffer */
  281.       p=buf; x=DIMP_CYLSIZE; while (x--) *p++ = 0;
  282.  
  283.       if (DImp_bitmap(info, cyl)) {
  284.         x = EndGetM32(info+dinf_cylinfo+(cyl<<2));
  285.         if (x != 0xFFFFFFFF && x != 0) {
  286.           UWORD length = x >> 16;
  287.  
  288.           if (length > DIMP_CYLSIZE) ERROR(INPUT);
  289.           READ(buf, length);
  290.  
  291.           if ((DImp_checksum(buf, length) & 0xFFFF) != (x & 0xFFFF))
  292.             ERROR(CHECKSUM);
  293.  
  294.           if (length != DIMP_CYLSIZE && !DImp_explode(buf,
  295.             info+dinf_ctable2, length, DIMP_CYLSIZE)) ERROR(DECRUNCH);
  296.         }
  297.       }
  298.       WRITE(buf, DIMP_CYLSIZE);
  299.     }
  300.     else {
  301.       /* skipping */
  302.       if (DImp_bitmap(info, cyl)) {
  303.         x = EndGetM32(info+dinf_cylinfo+(cyl<<2));
  304.         if (x != 0xFFFFFFFF && x != 0) SKIP(x >> 16);
  305.       }
  306.     }
  307.   }
  308.  
  309. exit_handler:
  310.   if (buf) FREE(buf);
  311.   return err;
  312. }
  313.  
  314. ASM(void) DImp_Free(REG(a0, struct xadArchiveInfo *ai), XADBASE) {
  315.   if (ai->xai_PrivateClient) {
  316.     FREE(ai->xai_PrivateClient);
  317.     ai->xai_PrivateClient = NULL;
  318.   }
  319. }
  320.  
  321.  
  322.  
  323.  
  324. #define HUNK_HEADER    1011
  325. #define HUNK_CODE    1001
  326.  
  327. ASM(BOOL) DImpSFX_RecogData(REG(d0, ULONG size), REG(a0, UBYTE *d), XADBASE) {
  328.   ULONG i;
  329.   if (size < 32
  330.   ||  EndGetM32(d)    != HUNK_HEADER
  331.   ||  EndGetM32(d+24) != HUNK_CODE) return 0;
  332.  
  333.   /* specific cases: DImp 1.00 = 3856; DImp 2.27 = 5796 */
  334.   if ((size >= 3860 && EndGetM32(d+3856) == 0x44494D50)
  335.   ||  (size >= 5800 && EndGetM32(d+5796) == 0x44494D50)) return 1;
  336.  
  337.   /* generic case - look just past the code hunk */
  338.   for (i = (EndGetM32(d+28)<<2) + 36; i < size; i+=4) {
  339.     if (EndGetM32(d+i) == 0x44494D50) return 1;
  340.   }
  341.  
  342.   return 0;
  343. }
  344.  
  345. ASM(LONG) DImpSFX_GetInfo(REG(a0, struct xadArchiveInfo *ai), XADBASE) {
  346.   ULONG readlen, offset = 0, i;
  347.   UBYTE *buf;
  348.   LONG err;
  349.  
  350.   readlen = ai->xai_InSize;
  351.   if (readlen > 6144) readlen = 6144;
  352.  
  353.   ALLOC(UBYTE *, buf, readlen);
  354.   READ(buf, readlen);
  355.  
  356.   for (i = (EndGetM32(buf+28)<<2) + 36; i < readlen; i+=4) {
  357.     if (EndGetM32(buf+i) == 0x44494D50) { offset = i; break; }
  358.   }
  359.  
  360.   err = XADERR_DATAFORMAT;
  361.  
  362. exit_handler:
  363.   if (buf) FREE(buf);
  364.  
  365.   /* if we found a match, actually look at the archive */
  366.   if (offset != 0) {
  367.     SKIP(offset - ai->xai_InPos);
  368.     err = DImp_GetInfo(ai, xadMasterBase);
  369.   }
  370.   return err;
  371. }
  372.  
  373.  
  374. const struct xadClient DImpSFX_Client = {
  375.   NEXTCLIENT, XADCLIENT_VERSION, 4, DIMP_VERSION, DIMP_REVISION,
  376.   6144, XADCF_DISKARCHIVER | XADCF_FREEDISKINFO |
  377.         XADCF_FREETEXTINFO | XADCF_FREETEXTINFOTEXT | XADCF_NOCHECKSIZE,
  378.   0, "DImp SFX",
  379.   (BOOL (*)()) DImpSFX_RecogData,
  380.   (LONG (*)()) DImpSFX_GetInfo,
  381.   (LONG (*)()) DImp_UnArchive,
  382.   (void (*)()) DImp_Free
  383. };
  384.  
  385. const struct xadClient DImp_Client = {
  386.   (struct xadClient *) &DImpSFX_Client, XADCLIENT_VERSION, 4,
  387.   DIMP_VERSION, DIMP_REVISION,
  388.   10, XADCF_DISKARCHIVER | XADCF_FREEDISKINFO |
  389.       XADCF_FREETEXTINFO | XADCF_FREETEXTINFOTEXT,
  390.   0, "DImp",
  391.   (BOOL (*)()) DImp_RecogData,
  392.   (LONG (*)()) DImp_GetInfo,
  393.   (LONG (*)()) DImp_UnArchive,
  394.   (void (*)()) DImp_Free
  395. };
  396.